"""
时间同步模块
提供高精度时间戳记录和时序管理功能
"""

import time
import numpy as np
from datetime import datetime, timezone
from typing import Dict, Any, Optional, List
from enum import Enum

from logger import Logger


class TimeEvent(Enum):
    """时间事件枚举"""
    # 基础事件
    SYSTEM_START = "system_start"
    INSTRUMENTS_CONNECTED = "instruments_connected"
    SPECTRUM_READY = "spectrum_ready"
    SIGNAL_PREPARED = "signal_prepared"
    SIGNAL_OUTPUT_ENABLED = "signal_output_enabled"
    TRIGGER_DETECTED = "trigger_detected"
    ACQUISITION_START = "acquisition_start"
    ACQUISITION_COMPLETE = "acquisition_complete"
    DATA_PROCESSING_START = "data_processing_start"
    DATA_SAVED = "data_saved"
    
    # 序列控制事件
    SEQUENCE_START = "sequence_start"
    SEQUENCE_COMPLETE = "sequence_complete"
    SYSTEM_INIT = "system_init"
    SYSTEM_INIT_COMPLETE = "system_init_complete"
    INSTRUMENT_CONNECT = "instrument_connect"
    INSTRUMENT_CONNECT_COMPLETE = "instrument_connect_complete"
    SPECTRUM_PREPARE = "spectrum_prepare"
    SPECTRUM_PREPARE_COMPLETE = "spectrum_prepare_complete"
    SPECTRUM_TRIGGER = "spectrum_trigger"
    SPECTRUM_TRIGGER_COMPLETE = "spectrum_trigger_complete"
    SIGNAL_PREPARE = "signal_prepare"
    SIGNAL_PREPARE_COMPLETE = "signal_prepare_complete"
    SIGNAL_OUTPUT = "signal_output"
    SIGNAL_OUTPUT_COMPLETE = "signal_output_complete"
    DATA_ACQUISITION = "data_acquisition"
    DATA_ACQUISITION_COMPLETE = "data_acquisition_complete"
    DATA_PROCESSING = "data_processing"
    DATA_PROCESSING_COMPLETE = "data_processing_complete"
    DATA_SAVE = "data_save"
    DATA_SAVE_COMPLETE = "data_save_complete"


class TimeSync:
    """时间同步管理器"""
    
    def __init__(self, logger: Optional[Logger] = None, precision: str = "ms"):
        """
        初始化时间同步管理器
        
        Args:
            logger: 日志记录器
            precision: 时间戳精度 ("ms", "us", "ns")
        """
        self.logger = logger or Logger("time_sync")
        self.precision = precision
        self.time_events: Dict[TimeEvent, float] = {}
        self.time_precision_factor = self._get_precision_factor()
        
        # 记录系统启动时间作为基准时间
        self.reference_time = self._get_current_time()
        self.time_events[TimeEvent.SYSTEM_START] = self.reference_time
        
        self.logger.info(f"时间同步管理器初始化，精度: {precision}")
        self.logger.info(f"基准时间: {self._format_timestamp(self.reference_time)}")
    
    def _get_precision_factor(self) -> float:
        """
        获取时间精度因子
        
        Returns:
            时间精度因子（秒为单位）
        """
        precision_map = {
            "ns": 1e-9,
            "us": 1e-6,
            "ms": 1e-3,
            "s": 1.0
        }
        return precision_map.get(self.precision, 1e-3)
    
    def _get_current_time(self) -> float:
        """
        获取当前时间（高精度）
        
        Returns:
            当前时间戳（秒）
        """
        return time.perf_counter()
    
    def _format_timestamp(self, timestamp: float) -> str:
        """
        格式化时间戳为可读字符串
        
        Args:
            timestamp: 时间戳
            
        Returns:
            格式化的时间字符串
        """
        # 计算相对于基准时间的偏移
        offset = timestamp - self.reference_time
        
        # 获取当前UTC时间
        utc_time = datetime.now(timezone.utc)
        
        return f"{utc_time.isoformat()} (offset: {offset:.6f}s)"
    
    def record_event(self, event: TimeEvent, description: Optional[str] = None) -> None:
        """
        记录时间事件
        
        Args:
            event: 时间事件
            description: 事件描述
        """
        current_time = self._get_current_time()
        self.time_events[event] = current_time
        
        log_msg = f"时间事件记录: {event.value}"
        if description:
            log_msg += f" - {description}"
        
        log_msg += f" 时间: {self._format_timestamp(current_time)}"
        self.logger.info(log_msg)
    
    def get_event_time(self, event: TimeEvent) -> Optional[float]:
        """
        获取事件时间
        
        Args:
            event: 时间事件
            
        Returns:
            事件时间戳，如果事件不存在则返回None
        """
        return self.time_events.get(event)
    
    def get_relative_time(self, event: TimeEvent, reference_event: TimeEvent) -> Optional[float]:
        """
        获取两个事件之间的相对时间
        
        Args:
            event: 目标事件
            reference_event: 参考事件
            
        Returns:
            相对时间（秒），如果任一事件不存在则返回None
        """
        event_time = self.get_event_time(event)
        ref_time = self.get_event_time(reference_event)
        
        if event_time is None or ref_time is None:
            return None
        
        return event_time - ref_time
    
    def get_all_events(self) -> Dict[TimeEvent, float]:
        """
        获取所有时间事件
        
        Returns:
            时间事件字典
        """
        return self.time_events.copy()
    
    def create_timing_metadata(self) -> Dict[str, Any]:
        """
        创建时序元数据
        
        Returns:
            时序元数据字典
        """
        metadata = {
            "reference_time": self.reference_time,
            "precision": self.precision,
            "utc_start_time": datetime.now(timezone.utc).isoformat(),
            "events": {},
            "relative_timing": {}
        }
        
        # 添加绝对时间戳
        for event, timestamp in self.time_events.items():
            metadata["events"][event.value] = {
                "timestamp": timestamp,
                "formatted": self._format_timestamp(timestamp)
            }
        
        # 计算相对时间关系
        reference_events = [
            TimeEvent.SPECTRUM_READY,
            TimeEvent.SIGNAL_PREPARED,
            TimeEvent.SIGNAL_OUTPUT_ENABLED,
            TimeEvent.TRIGGER_DETECTED,
            TimeEvent.ACQUISITION_START
        ]
        
        for event in reference_events:
            relative_time = self.get_relative_time(event, TimeEvent.SPECTRUM_READY)
            if relative_time is not None:
                metadata["relative_timing"][event.value] = relative_time
        
        return metadata
    
    def generate_time_offsets(self, sample_rate: float, num_samples: int, 
                            start_event: TimeEvent = TimeEvent.ACQUISITION_START) -> np.ndarray:
        """
        生成采样点的时间偏移数组
        
        Args:
            sample_rate: 采样率 (Hz)
            num_samples: 采样点数
            start_event: 起始事件
            
        Returns:
            时间偏移数组（秒）
        """
        start_time = self.get_event_time(start_event)
        if start_time is None:
            self.logger.warning(f"起始事件 {start_event.value} 未记录")
            return np.arange(num_samples) / sample_rate
        
        # 生成相对于起始事件的时间偏移
        time_offsets = np.arange(num_samples) / sample_rate
        
        self.logger.info(f"生成时间偏移数组: 起始事件={start_event.value}, "
                        f"采样率={sample_rate} Hz, 样本数={num_samples}, "
                        f"时长={time_offsets[-1]:.6f} s")
        
        return time_offsets
    
    def get_acquisition_timing_info(self, sample_rate: float, num_samples: int) -> Dict[str, Any]:
        """
        获取数据采集的时序信息
        
        Args:
            sample_rate: 采样率
            num_samples: 采样点数
            
        Returns:
            采集时序信息字典
        """
        timing_info = {
            "sample_rate": sample_rate,
            "num_samples": num_samples,
            "duration_seconds": num_samples / sample_rate,
            "timing_events": {},
            "relative_offsets": {}
        }
        
        # 添加关键时序事件
        key_events = [
            TimeEvent.SPECTRUM_READY,
            TimeEvent.SIGNAL_PREPARED,
            TimeEvent.SIGNAL_OUTPUT_ENABLED,
            TimeEvent.TRIGGER_DETECTED,
            TimeEvent.ACQUISITION_START,
            TimeEvent.ACQUISITION_COMPLETE
        ]
        
        for event in key_events:
            event_time = self.get_event_time(event)
            if event_time is not None:
                timing_info["timing_events"][event.value] = {
                    "absolute_time": event_time,
                    "formatted": self._format_timestamp(event_time)
                }
        
        # 计算相对于采集开始的时间偏移
        if self.get_event_time(TimeEvent.ACQUISITION_START) is not None:
            for event in key_events:
                rel_time = self.get_relative_time(event, TimeEvent.ACQUISITION_START)
                if rel_time is not None:
                    timing_info["relative_offsets"][event.value] = rel_time
        
        return timing_info
    
    def reset(self) -> None:
        """重置时间同步管理器"""
        self.time_events.clear()
        self.reference_time = self._get_current_time()
        self.time_events[TimeEvent.SYSTEM_START] = self.reference_time
        self.logger.info("时间同步管理器已重置")
    
    def validate_timing_sequence(self) -> bool:
        """
        验证时序序列的合理性
        
        Returns:
            时序序列是否合理
        """
        expected_sequence = [
            TimeEvent.SPECTRUM_READY,
            TimeEvent.SIGNAL_PREPARED,
            TimeEvent.SIGNAL_OUTPUT_ENABLED,
            TimeEvent.TRIGGER_DETECTED,
            TimeEvent.ACQUISITION_START,
            TimeEvent.ACQUISITION_COMPLETE
        ]
        
        for i in range(len(expected_sequence) - 1):
            current_event = expected_sequence[i]
            next_event = expected_sequence[i + 1]
            
            current_time = self.get_event_time(current_event)
            next_time = self.get_event_time(next_event)
            
            if current_time is None:
                self.logger.warning(f"缺少事件: {current_event.value}")
                return False
            
            if next_time is not None and next_time < current_time:
                self.logger.error(f"时序错误: {next_event.value} 在 {current_event.value} 之前")
                return False
        
        self.logger.info("时序序列验证通过")
        return True